unit BaseModel;

interface

uses System.SysUtils, System.JSON, DBXJSONReflect, System.Generics.Collections,DAOInterface;

type
  TBaseModel = class{(TInterfacedobject)} abstract

  protected
    FFields: TDictionary<String, variant>;

//    procedure save(data:TBaseModel);
//    procedure pudate(data:TBaseModel);
  public
    { public declarations }
    class function ObjectToJSON<TT: class>(MyObject: TT; AMarshal: TJSONMarshal)
      : TJSONValue;
    class function JSONToObject<TT: class>(JSON: TJSONValue;
      AUnMarshal: TJSONUnMarshal): TT;

    class procedure RegisterConverter(m: TJSONMarshal); virtual;
    class procedure RegisterReverter(unm: TJSONUnMarshal); virtual;
    class function DateToStr(d: TDate): string;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure put(name: string; value: variant);
    function getvalue(name: string): variant;

    procedure CopyFrom(s: TBaseModel); virtual;

  end;

implementation

uses variants;

{ TBaseModel }

procedure TBaseModel.CopyFrom(s: TBaseModel);
var
  k: string;
begin
  self.FFields.Clear;
  for k in s.FFields.Keys do
  begin
    self.FFields.Add(k, s.FFields[k]);
  end;

end;

constructor TBaseModel.Create;
begin
  FFields := TDictionary<String, variant>.Create;

end;

class function TBaseModel.DateToStr(d: TDate): string;
begin
  result := FormatDateTime('yyyy/mm/dd', d);
end;

destructor TBaseModel.Destroy;
begin
  FFields.Free;
  inherited;
end;


function TBaseModel.getvalue(name: string): variant;
begin
  try
    result := FFields[string.UpperCase(name)];
  except
    result := Null;
  end;

end;

class function TBaseModel.JSONToObject<TT>(JSON: TJSONValue;
  AUnMarshal: TJSONUnMarshal): TT;
var
  UnMarshal: TJSONUnMarshal;
begin
  if JSON is TJSONNull then
    exit(nil);

  if Assigned(AUnMarshal) then
    UnMarshal := AUnMarshal
  else
    UnMarshal := TJSONUnMarshal.Create;

  RegisterReverter(UnMarshal);
  try
    exit(TT(UnMarshal.UnMarshal(JSON)))
  finally
    if not Assigned(AUnMarshal) then
      UnMarshal.Free;
  end;

end;

class function TBaseModel.ObjectToJSON<TT>(MyObject: TT; AMarshal: TJSONMarshal)
  : TJSONValue;
var
  Marshal: TJSONMarshal;
begin

  if Assigned(MyObject) then
  begin

    if Assigned(AMarshal) then
      Marshal := AMarshal
    else
      Marshal := TJSONMarshal.Create(TJSONConverter.Create);

    RegisterConverter(Marshal);
    try
      exit(Marshal.Marshal(MyObject));
    finally
      if not Assigned(AMarshal) then
        Marshal.Free;
    end;
  end
  else
    exit(TJSONNull.Create);

end;

procedure TBaseModel.put(name: string; value: variant);
begin

  FFields.AddOrSetValue(string.UpperCase(name), value);
end;

class procedure TBaseModel.RegisterConverter(m: TJSONMarshal);
begin

end;

class procedure TBaseModel.RegisterReverter(unm: TJSONUnMarshal);
begin

end;

initialization
finalization
end.
